home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / liboctave / data-conv.cc < prev    next >
C/C++ Source or Header  |  1996-12-06  |  16KB  |  711 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <cctype>
  28.  
  29. #include <iostream.h>
  30.  
  31. #include "byte-swap.h"
  32. #include "data-conv.h"
  33. #include "lo-error.h"
  34.  
  35. oct_data_conv::data_type
  36. oct_data_conv::string_to_data_type (const string& str)
  37. {
  38.   data_type retval = dt_unknown;
  39.  
  40.     // XXX FIXME XXX -- finish implementing this.
  41.  
  42.   // XXX FIXME XXX -- before checking s, need to strip spaces and downcase.
  43.  
  44.   int n = str.length ();
  45.  
  46.   int k = 0;
  47.  
  48.   string s (n, ' ');
  49.  
  50.   for (int i = 0; i < n; i++)
  51.     if (! isspace (str[i]))
  52.       s[k++] = tolower (str[i]);
  53.  
  54.   s.resize (k);
  55.  
  56.   if (s == "char" || s == "char*1" || s == "integer*1" || s == "int8")
  57.     retval = dt_char;
  58.   else if (s == "schar" || s == "signedchar")
  59.     retval = dt_schar;
  60.   else if (s == "uchar" || s == "unsignedchar")
  61.     retval = dt_uchar;
  62.   else if (s == "short")
  63.     retval = dt_short;
  64.   else if (s == "ushort" || s == "unsignedshort")
  65.     retval = dt_ushort;
  66.   else if (s == "int")
  67.     retval = dt_int;
  68.   else if (s == "uint" || s == "unsignedint")
  69.     retval = dt_uint;
  70.   else if (s == "long")
  71.     retval = dt_long;
  72.   else if (s == "ulong" || s == "unsignedlong")
  73.     retval = dt_ulong;
  74.   else if (s == "float" || s == "float32" || s == "real*4")
  75.     retval = dt_float;
  76.   else if (s == "double" || s == "float64" || s == "real*8")
  77.     retval = dt_double;
  78.   else if (s == "int16" || s == "integer*2")
  79.     {
  80.       if (sizeof (short) == 2)
  81.     retval = dt_short;
  82.       else if (sizeof (int) == 2)
  83.     retval = dt_int;
  84.       else
  85.     (*current_liboctave_error_handler)
  86.       ("unable to find matching native data type for %s", s.c_str ());
  87.     }
  88.   else if (s == "int32" || s == "integer*4")
  89.     {
  90.       if (sizeof (int) == 4)
  91.     retval = dt_int;
  92.       else if (sizeof (long) == 4)
  93.     retval = dt_long;
  94.       else
  95.     (*current_liboctave_error_handler)
  96.       ("unable to find matching native data type for %s", s.c_str ());
  97.     }
  98.   else
  99.     (*current_liboctave_error_handler) ("invalid data type specified");
  100.  
  101.   return retval;
  102. }
  103.  
  104. #define swap_1_bytes(x, y)
  105.  
  106. #define LS_DO_READ(TYPE,swap,data,size,len,stream) \
  107.   do \
  108.     { \
  109.       volatile TYPE *ptr = (TYPE *) data; \
  110.       stream.read ((TYPE *) ptr, size * len); \
  111.       if (swap) \
  112.         swap_ ## size ## _bytes ((char *) ptr, len); \
  113.       TYPE tmp = ptr[0]; \
  114.       for (int i = len - 1; i > 0; i--) \
  115.         data[i] = ptr[i]; \
  116.       data[0] = tmp; \
  117.     } \
  118.   while (0)
  119.  
  120. // Have to use copy here to avoid writing over data accessed via
  121. // Matrix::data().
  122.  
  123. #define LS_DO_WRITE(TYPE,data,size,len,stream) \
  124.   do \
  125.     { \
  126.       char tmp_type = (char) type; \
  127.       stream.write (&tmp_type, 1); \
  128.       TYPE *ptr = new TYPE [len]; \
  129.       for (int i = 0; i < len; i++) \
  130.         ptr[i] = (TYPE) data[i]; \
  131.       stream.write ((TYPE *) ptr, size * len); \
  132.       delete [] ptr ; \
  133.     } \
  134.   while (0)
  135.  
  136. // Loading variables from files.
  137.  
  138. static void
  139. gripe_unrecognized_float_fmt (void)
  140. {
  141.   (*current_liboctave_error_handler)
  142.     ("unrecognized floating point format requested");
  143. }
  144.  
  145. static void
  146. gripe_data_conversion (const char *from, const char *to)
  147. {
  148.   (*current_liboctave_error_handler)
  149.     ("unable to convert from %s to %s format", from, to);
  150. }
  151.  
  152. // But first, some data conversion routines.
  153.  
  154. // Currently, we only handle conversions for the IEEE types.  To fix
  155. // that, make more of the following routines work.
  156.  
  157. // XXX FIXME XXX -- assumes sizeof (Complex) == 8
  158. // XXX FIXME XXX -- assumes sizeof (double) == 8
  159. // XXX FIXME XXX -- assumes sizeof (float) == 4
  160.  
  161. static void
  162. IEEE_big_double_to_IEEE_little_double (double *d, int len)
  163. {
  164.   swap_8_bytes ((char *) d, len);
  165. }
  166.  
  167. static void
  168. VAX_D_double_to_IEEE_little_double (double * /* d */, int /* len */)
  169. {
  170.   gripe_data_conversion ("VAX D float", "IEEE little endian format");
  171. }
  172.  
  173. static void
  174. VAX_G_double_to_IEEE_little_double (double * /* d */, int /* len */)
  175. {
  176.   gripe_data_conversion ("VAX G float", "IEEE little endian format");
  177. }
  178.  
  179. static void
  180. Cray_to_IEEE_little_double (double * /* d */, int /* len */)
  181. {
  182.   gripe_data_conversion ("Cray", "IEEE little endian format");
  183. }
  184.  
  185. static void
  186. IEEE_big_float_to_IEEE_little_float (float *d, int len)
  187. {
  188.   swap_4_bytes ((char *) d, len);
  189. }
  190.  
  191. static void
  192. VAX_D_float_to_IEEE_little_float (float * /* d */, int /* len */)
  193. {
  194.   gripe_data_conversion ("VAX D float", "IEEE little endian format");
  195. }
  196.  
  197. static void
  198. VAX_G_float_to_IEEE_little_float (float * /* d */, int /* len */)
  199. {
  200.   gripe_data_conversion ("VAX G float", "IEEE little endian format");
  201. }
  202.  
  203. static void
  204. Cray_to_IEEE_little_float (float * /* d */, int /* len */)
  205. {
  206.   gripe_data_conversion ("Cray", "IEEE little endian format");
  207. }
  208.  
  209. static void
  210. IEEE_little_double_to_IEEE_big_double (double *d, int len)
  211. {
  212.   swap_8_bytes ((char *) d, len);
  213. }
  214.  
  215. static void
  216. VAX_D_double_to_IEEE_big_double (double * /* d */, int /* len */)
  217. {
  218.   gripe_data_conversion ("VAX D float", "IEEE big endian format");
  219. }
  220.  
  221. static void
  222. VAX_G_double_to_IEEE_big_double (double * /* d */, int /* len */)
  223. {
  224.   gripe_data_conversion ("VAX G float", "IEEE big endian format");
  225. }
  226.  
  227. static void
  228. Cray_to_IEEE_big_double (double * /* d */, int /* len */)
  229. {
  230.   gripe_data_conversion ("Cray", "IEEE big endian format");
  231. }
  232.  
  233. static void
  234. IEEE_little_float_to_IEEE_big_float (float *d, int len)
  235. {
  236.   swap_4_bytes ((char *) d, len);
  237. }
  238.  
  239. static void
  240. VAX_D_float_to_IEEE_big_float (float * /* d */, int /* len */)
  241. {
  242.   gripe_data_conversion ("VAX D float", "IEEE big endian format");
  243. }
  244.  
  245. static void
  246. VAX_G_float_to_IEEE_big_float (float * /* d */, int /* len */)
  247. {
  248.   gripe_data_conversion ("VAX G float", "IEEE big endian format");
  249. }
  250.  
  251. static void
  252. Cray_to_IEEE_big_float (float * /* d */, int /* len */)
  253. {
  254.   gripe_data_conversion ("Cray", "IEEE big endian format");
  255. }
  256.  
  257. static void
  258. IEEE_little_double_to_VAX_D_double (double * /* d */, int /* len */)
  259. {
  260.   gripe_data_conversion ("IEEE little endian", "VAX D");
  261. }
  262.  
  263. static void
  264. IEEE_big_double_to_VAX_D_double (double * /* d */, int /* len */)
  265. {
  266.   gripe_data_conversion ("IEEE big endian", "VAX D");
  267. }
  268.  
  269. static void
  270. VAX_G_double_to_VAX_D_double (double * /* d */, int /* len */)
  271. {
  272.   gripe_data_conversion ("VAX G float", "VAX D");
  273. }
  274.  
  275. static void
  276. Cray_to_VAX_D_double (double * /* d */, int /* len */)
  277. {
  278.   gripe_data_conversion ("Cray", "VAX D");
  279. }
  280.  
  281. static void
  282. IEEE_little_float_to_VAX_D_float (float * /* d */, int /* len */)
  283. {
  284.   gripe_data_conversion ("IEEE little endian", "VAX D");
  285. }
  286.  
  287. static void
  288. IEEE_big_float_to_VAX_D_float (float * /* d */, int /* len */)
  289. {
  290.   gripe_data_conversion ("IEEE big endian", "VAX D");
  291. }
  292.  
  293. static void
  294. VAX_G_float_to_VAX_D_float (float * /* d */, int /* len */)
  295. {
  296.   gripe_data_conversion ("VAX G float", "VAX D");
  297. }
  298.  
  299. static void
  300. Cray_to_VAX_D_float (float * /* d */, int /* len */)
  301. {
  302.   gripe_data_conversion ("Cray", "VAX D");
  303. }
  304.  
  305. static void
  306. IEEE_little_double_to_VAX_G_double (double * /* d */, int /* len */)
  307. {
  308.   gripe_data_conversion ("IEEE little endian", "VAX G");
  309. }
  310.  
  311. static void
  312. IEEE_big_double_to_VAX_G_double (double * /* d */, int /* len */)
  313. {
  314.   gripe_data_conversion ("IEEE big endian", "VAX G");
  315. }
  316.  
  317. static void
  318. VAX_D_double_to_VAX_G_double (double * /* d */, int /* len */)
  319. {
  320.   gripe_data_conversion ("VAX D float", "VAX G");
  321. }
  322.  
  323. static void
  324. Cray_to_VAX_G_double (double * /* d */, int /* len */)
  325. {
  326.   gripe_data_conversion ("VAX G float", "VAX G");
  327. }
  328.  
  329. static void
  330. IEEE_little_float_to_VAX_G_float (float * /* d */, int /* len */)
  331. {
  332.   gripe_data_conversion ("IEEE little endian", "VAX G");
  333. }
  334.  
  335. static void
  336. IEEE_big_float_to_VAX_G_float (float * /* d */, int /* len */)
  337. {
  338.   gripe_data_conversion ("IEEE big endian", "VAX G");
  339. }
  340.  
  341. static void
  342. VAX_D_float_to_VAX_G_float (float * /* d */, int /* len */)
  343. {
  344.   gripe_data_conversion ("VAX D float", "VAX G");
  345. }
  346.  
  347. static void
  348. Cray_to_VAX_G_float (float * /* d */, int /* len */)
  349. {
  350.   gripe_data_conversion ("VAX G float", "VAX G");
  351. }
  352.  
  353. void
  354. do_double_format_conversion (double *data, int len,
  355.                  oct_mach_info::float_format fmt)
  356. {
  357.   switch (oct_mach_info::native_float_format ())
  358.     {
  359.     case oct_mach_info::ieee_little_endian:
  360.       switch (fmt)
  361.     {
  362.     case oct_mach_info::ieee_little_endian:
  363.       break;
  364.  
  365.     case oct_mach_info::ieee_big_endian:
  366.       IEEE_big_double_to_IEEE_little_double (data, len);
  367.       break;
  368.  
  369.     case oct_mach_info::vax_d:
  370.       VAX_D_double_to_IEEE_little_double (data, len);
  371.       break;
  372.  
  373.     case oct_mach_info::vax_g:
  374.       VAX_G_double_to_IEEE_little_double (data, len);
  375.       break;
  376.  
  377.     case oct_mach_info::cray:
  378.       Cray_to_IEEE_little_double (data, len);
  379.       break;
  380.  
  381.     default:
  382.       gripe_unrecognized_float_fmt ();
  383.       break;
  384.     }
  385.       break;
  386.  
  387.     case oct_mach_info::ieee_big_endian:
  388.       switch (fmt)
  389.     {
  390.     case oct_mach_info::ieee_little_endian:
  391.       IEEE_little_double_to_IEEE_big_double (data, len);
  392.       break;
  393.  
  394.     case oct_mach_info::ieee_big_endian:
  395.       break;
  396.  
  397.     case oct_mach_info::vax_d:
  398.       VAX_D_double_to_IEEE_big_double (data, len);
  399.       break;
  400.  
  401.     case oct_mach_info::vax_g:
  402.       VAX_G_double_to_IEEE_big_double (data, len);
  403.       break;
  404.  
  405.     case oct_mach_info::cray:
  406.       Cray_to_IEEE_big_double (data, len);
  407.       break;
  408.  
  409.     default:
  410.       gripe_unrecognized_float_fmt ();
  411.       break;
  412.     }
  413.       break;
  414.  
  415.     case oct_mach_info::vax_d:
  416.       switch (fmt)
  417.     {
  418.     case oct_mach_info::ieee_little_endian:
  419.       IEEE_little_double_to_VAX_D_double (data, len);
  420.       break;
  421.  
  422.     case oct_mach_info::ieee_big_endian:
  423.       IEEE_big_double_to_VAX_D_double (data, len);
  424.       break;
  425.  
  426.     case oct_mach_info::vax_d:
  427.       break;
  428.  
  429.     case oct_mach_info::vax_g:
  430.       VAX_G_double_to_VAX_D_double (data, len);
  431.       break;
  432.  
  433.     case oct_mach_info::cray:
  434.       Cray_to_VAX_D_double (data, len);
  435.       break;
  436.  
  437.     default:
  438.       gripe_unrecognized_float_fmt ();
  439.       break;
  440.     }
  441.       break;
  442.  
  443.     case oct_mach_info::vax_g:
  444.       switch (fmt)
  445.     {
  446.     case oct_mach_info::ieee_little_endian:
  447.       IEEE_little_double_to_VAX_G_double (data, len);
  448.       break;
  449.  
  450.     case oct_mach_info::ieee_big_endian:
  451.       IEEE_big_double_to_VAX_G_double (data, len);
  452.       break;
  453.  
  454.     case oct_mach_info::vax_d:
  455.       VAX_D_double_to_VAX_G_double (data, len);
  456.       break;
  457.  
  458.     case oct_mach_info::vax_g:
  459.       break;
  460.  
  461.     case oct_mach_info::cray:
  462.       Cray_to_VAX_G_double (data, len);
  463.       break;
  464.  
  465.     default:
  466.       gripe_unrecognized_float_fmt ();
  467.       break;
  468.     }
  469.       break;
  470.  
  471.     default:
  472.       (*current_liboctave_error_handler)
  473.     ("impossible state reached in file `%s' at line %d",
  474.      __FILE__, __LINE__);
  475.       break;
  476.     }
  477. }
  478.  
  479. void
  480. do_float_format_conversion (float *data, int len,
  481.                 oct_mach_info::float_format fmt)
  482. {
  483.   switch (oct_mach_info::native_float_format ())
  484.     {
  485.     case oct_mach_info::ieee_little_endian:
  486.       switch (fmt)
  487.     {
  488.     case oct_mach_info::ieee_little_endian:
  489.       break;
  490.  
  491.     case oct_mach_info::ieee_big_endian:
  492.       IEEE_big_float_to_IEEE_little_float (data, len);
  493.       break;
  494.  
  495.     case oct_mach_info::vax_d:
  496.       VAX_D_float_to_IEEE_little_float (data, len);
  497.       break;
  498.  
  499.     case oct_mach_info::vax_g:
  500.       VAX_G_float_to_IEEE_little_float (data, len);
  501.       break;
  502.  
  503.     case oct_mach_info::cray:
  504.       Cray_to_IEEE_little_float (data, len);
  505.       break;
  506.  
  507.     default:
  508.       gripe_unrecognized_float_fmt ();
  509.       break;
  510.     }
  511.       break;
  512.  
  513.     case oct_mach_info::ieee_big_endian:
  514.       switch (fmt)
  515.     {
  516.     case oct_mach_info::ieee_little_endian:
  517.       IEEE_little_float_to_IEEE_big_float (data, len);
  518.       break;
  519.  
  520.     case oct_mach_info::ieee_big_endian:
  521.       break;
  522.  
  523.     case oct_mach_info::vax_d:
  524.       VAX_D_float_to_IEEE_big_float (data, len);
  525.       break;
  526.  
  527.     case oct_mach_info::vax_g:
  528.       VAX_G_float_to_IEEE_big_float (data, len);
  529.       break;
  530.  
  531.     case oct_mach_info::cray:
  532.       Cray_to_IEEE_big_float (data, len);
  533.       break;
  534.  
  535.     default:
  536.       gripe_unrecognized_float_fmt ();
  537.       break;
  538.     }
  539.       break;
  540.  
  541.     case oct_mach_info::vax_d:
  542.       switch (fmt)
  543.     {
  544.     case oct_mach_info::ieee_little_endian:
  545.       IEEE_little_float_to_VAX_D_float (data, len);
  546.       break;
  547.  
  548.     case oct_mach_info::ieee_big_endian:
  549.       IEEE_big_float_to_VAX_D_float (data, len);
  550.       break;
  551.  
  552.     case oct_mach_info::vax_d:
  553.       break;
  554.  
  555.     case oct_mach_info::vax_g:
  556.       VAX_G_float_to_VAX_D_float (data, len);
  557.       break;
  558.  
  559.     case oct_mach_info::cray:
  560.       Cray_to_VAX_D_float (data, len);
  561.       break;
  562.  
  563.     default:
  564.       gripe_unrecognized_float_fmt ();
  565.       break;
  566.     }
  567.       break;
  568.  
  569.     case oct_mach_info::vax_g:
  570.       switch (fmt)
  571.     {
  572.     case oct_mach_info::ieee_little_endian:
  573.       IEEE_little_float_to_VAX_G_float (data, len);
  574.       break;
  575.  
  576.     case oct_mach_info::ieee_big_endian:
  577.       IEEE_big_float_to_VAX_G_float (data, len);
  578.       break;
  579.  
  580.     case oct_mach_info::vax_d:
  581.       VAX_D_float_to_VAX_G_float (data, len);
  582.       break;
  583.  
  584.     case oct_mach_info::vax_g:
  585.       break;
  586.  
  587.     case oct_mach_info::cray:
  588.       Cray_to_VAX_G_float (data, len);
  589.       break;
  590.  
  591.     default:
  592.       gripe_unrecognized_float_fmt ();
  593.       break;
  594.     }
  595.       break;
  596.  
  597.     default:
  598.       (*current_liboctave_error_handler)
  599.     ("impossible state reached in file `%s' at line %d",
  600.      __FILE__, __LINE__);
  601.       break;
  602.     }
  603. }
  604.  
  605. void
  606. read_doubles (istream& is, double *data, save_type type, int len,
  607.           int swap, oct_mach_info::float_format fmt)
  608. {
  609.   switch (type)
  610.     {
  611.     case LS_U_CHAR:
  612.       LS_DO_READ (unsigned char, swap, data, 1, len, is);
  613.       break;
  614.  
  615.     case LS_U_SHORT:
  616.       LS_DO_READ (unsigned TWO_BYTE_INT, swap, data, 2, len, is);
  617.       break;
  618.  
  619.     case LS_U_INT:
  620.       LS_DO_READ (unsigned FOUR_BYTE_INT, swap, data, 4, len, is);
  621.       break;
  622.  
  623.     case LS_CHAR:
  624.       LS_DO_READ (signed char, swap, data, 1, len, is);
  625.       break;
  626.  
  627.     case LS_SHORT:
  628.       LS_DO_READ (TWO_BYTE_INT, swap, data, 2, len, is);
  629.       break;
  630.  
  631.     case LS_INT:
  632.       LS_DO_READ (FOUR_BYTE_INT, swap, data, 4, len, is);
  633.       break;
  634.  
  635.     case LS_FLOAT:
  636.       {
  637.     volatile float *ptr = (float *) data;
  638.     is.read (data, 4 * len);
  639.     do_float_format_conversion ((float *) data, len, fmt);
  640.     float tmp = ptr[0];
  641.     for (int i = len - 1; i > 0; i--)
  642.       data[i] = ptr[i];
  643.     data[0] = tmp;
  644.       }
  645.       break;
  646.  
  647.     case LS_DOUBLE:
  648.       is.read (data, 8 * len);
  649.       do_double_format_conversion (data, len, fmt);
  650.       break;
  651.  
  652.     default:
  653.       is.clear (ios::failbit|is.rdstate ());
  654.       break;
  655.     }
  656. }
  657.  
  658. void
  659. write_doubles (ostream& os, const double *data, save_type type, int len)
  660. {
  661.   switch (type)
  662.     {
  663.     case LS_U_CHAR:
  664.       LS_DO_WRITE (unsigned char, data, 1, len, os);
  665.       break;
  666.  
  667.     case LS_U_SHORT:
  668.       LS_DO_WRITE (unsigned TWO_BYTE_INT, data, 2, len, os);
  669.       break;
  670.  
  671.     case LS_U_INT:
  672.       LS_DO_WRITE (unsigned FOUR_BYTE_INT, data, 4, len, os);
  673.       break;
  674.  
  675.     case LS_CHAR:
  676.       LS_DO_WRITE (signed char, data, 1, len, os);
  677.       break;
  678.  
  679.     case LS_SHORT:
  680.       LS_DO_WRITE (TWO_BYTE_INT, data, 2, len, os);
  681.       break;
  682.  
  683.     case LS_INT:
  684.       LS_DO_WRITE (FOUR_BYTE_INT, data, 4, len, os);
  685.       break;
  686.  
  687.     case LS_FLOAT:
  688.       LS_DO_WRITE (float, data, 4, len, os);
  689.       break;
  690.  
  691.     case LS_DOUBLE:
  692.       {
  693.     char tmp_type = (char) type;
  694.     os.write (&tmp_type, 1);
  695.     os.write (data, 8 * len);
  696.       }
  697.       break;
  698.  
  699.     default:
  700.       (*current_liboctave_error_handler)
  701.     ("unrecognized data format requested");
  702.       break;
  703.     }
  704. }
  705.  
  706. /*
  707. ;;; Local Variables: ***
  708. ;;; mode: C++ ***
  709. ;;; End: ***
  710. */
  711.